"""
手指掩码生成模块 - 专注于手指方向掩码的生成

此模块负责根据手指位置和方向生成掩码，用于后续的内容匹配。
"""
import cv2
import numpy as np
from typing import Tuple, Optional


class FingerMaskGenerator:
    """
    手指掩码生成器类，专注于手指方向掩码的生成

    功能包括：
    - 根据手指位置和方向生成掩码
    - 掩码的可视化
    - 掩码参数的调整
    """

    def __init__(self, extension_length: int = 200, extension_width: int = 50):
        """
        初始化手指掩码生成器

        参数:
            extension_length: 手指方向延伸长度
            extension_width: 手指方向延伸宽度
        """
        self.extension_length = extension_length
        self.extension_width = extension_width

    def create_finger_direction_mask(self, image_shape: Tuple[int, int],
                                     finger_tip: Tuple[int, int],
                                     finger_direction: Tuple[float, float],
                                     length_factor: float = 1.0) -> np.ndarray:
        """
        创建手指方向掩码

        参数:
            image_shape: 图像形状 (高度, 宽度)
            finger_tip: 指尖坐标 (x, y)
            finger_direction: 手指方向向量 (dx, dy)
            length_factor: 长度系数，用于调整掩码长度

        返回:
            np.ndarray: 手指方向掩码
        """
        h, w = image_shape
        mask = np.zeros((h, w), dtype=np.uint8)

        # 确保指尖在图像内
        finger_tip = self._clamp_point_to_image(finger_tip, w, h)

        # 计算延伸长度
        extension_length = int(self.extension_length * length_factor)

        # 计算延伸终点
        end_point = self._calculate_end_point(
            finger_tip, finger_direction, extension_length, w, h)

        # 计算四边形的四个顶点
        quad_points = self._calculate_quad_points(
            finger_tip, end_point, finger_direction, w, h)

        # 绘制填充的四边形
        cv2.fillPoly(mask, [quad_points], (255))

        return mask

    def _clamp_point_to_image(self, point: Tuple[int, int], width: int, height: int) -> Tuple[int, int]:
        """将点限制在图像范围内"""
        x, y = point
        if not (0 <= x < width and 0 <= y < height):
            x = min(max(0, x), width-1)
            y = min(max(0, y), height-1)
        return (x, y)

    def _calculate_end_point(self, finger_tip: Tuple[int, int],
                             finger_direction: Tuple[float, float],
                             extension_length: int, width: int, height: int) -> Tuple[int, int]:
        """计算延伸终点"""
        end_x = int(finger_tip[0] + finger_direction[0] * extension_length)
        end_y = int(finger_tip[1] + finger_direction[1] * extension_length)

        # 确保终点不超出图像范围
        end_x = min(max(0, end_x), width-1)
        end_y = min(max(0, end_y), height-1)

        return (end_x, end_y)

    def _calculate_quad_points(self, finger_tip: Tuple[int, int],
                               end_point: Tuple[int, int],
                               finger_direction: Tuple[float, float],
                               width: int, height: int) -> np.ndarray:
        """计算四边形的四个顶点"""
        # 计算垂直于方向的向量
        perp_x = -finger_direction[1]
        perp_y = finger_direction[0]

        # 计算四边形的四个顶点
        half_width = self.extension_width // 2

        pt1 = (
            int(finger_tip[0] - perp_x * half_width),
            int(finger_tip[1] - perp_y * half_width)
        )
        pt2 = (
            int(finger_tip[0] + perp_x * half_width),
            int(finger_tip[1] + perp_y * half_width)
        )
        pt3 = (
            int(end_point[0] + perp_x * half_width),
            int(end_point[1] + perp_y * half_width)
        )
        pt4 = (
            int(end_point[0] - perp_x * half_width),
            int(end_point[1] - perp_y * half_width)
        )

        # 将所有点限制在图像范围内
        pts = np.array([
            (min(max(0, pt[0]), width-1), min(max(0, pt[1]), height-1))
            for pt in [pt1, pt2, pt3, pt4]
        ], dtype=np.int32)

        return pts

    def expand_mask(self, mask: np.ndarray, kernel_size: int = 5,
                    iterations: int = 2) -> np.ndarray:
        """
        扩大掩码

        参数:
            mask: 输入掩码
            kernel_size: 膨胀核大小
            iterations: 膨胀迭代次数

        返回:
            np.ndarray: 扩大后的掩码
        """
        kernel = np.ones((kernel_size, kernel_size), np.uint8)
        return cv2.dilate(mask, kernel, iterations=iterations)

    def draw_finger_mask(self, image: np.ndarray, finger_mask: np.ndarray,
                         color: Tuple[int, int, int] = (0, 0, 255),
                         alpha: float = 0.3) -> np.ndarray:
        """
        在图像上绘制手指方向掩码

        参数:
            image: 输入图像
            finger_mask: 手指方向掩码
            color: 掩码颜色
            alpha: 透明度

        返回:
            np.ndarray: 绘制了手指方向掩码的图像
        """
        result_image = image.copy()

        # 创建彩色掩码
        color_mask = np.zeros_like(result_image)
        color_mask[finger_mask > 0] = color

        # 将掩码与原图叠加
        cv2.addWeighted(color_mask, alpha, result_image,
                        1 - alpha, 0, result_image)

        return result_image

    def create_circular_mask(self, image_shape: Tuple[int, int],
                             center: Tuple[int, int], radius: int) -> np.ndarray:
        """
        创建圆形掩码

        参数:
            image_shape: 图像形状 (高度, 宽度)
            center: 圆心坐标 (x, y)
            radius: 半径

        返回:
            np.ndarray: 圆形掩码
        """
        h, w = image_shape
        mask = np.zeros((h, w), dtype=np.uint8)

        # 确保圆心在图像内
        center = self._clamp_point_to_image(center, w, h)

        # 绘制填充的圆
        cv2.circle(mask, center, radius, (255), -1)

        return mask

    def create_rectangular_mask(self, image_shape: Tuple[int, int],
                                top_left: Tuple[int, int],
                                bottom_right: Tuple[int, int]) -> np.ndarray:
        """
        创建矩形掩码

        参数:
            image_shape: 图像形状 (高度, 宽度)
            top_left: 左上角坐标 (x, y)
            bottom_right: 右下角坐标 (x, y)

        返回:
            np.ndarray: 矩形掩码
        """
        h, w = image_shape
        mask = np.zeros((h, w), dtype=np.uint8)

        # 确保坐标在图像内
        top_left = self._clamp_point_to_image(top_left, w, h)
        bottom_right = self._clamp_point_to_image(bottom_right, w, h)

        # 绘制填充的矩形
        cv2.rectangle(mask, top_left, bottom_right, (255), -1)

        return mask

    def combine_masks(self, mask1: np.ndarray, mask2: np.ndarray,
                      operation: str = 'or') -> np.ndarray:
        """
        组合两个掩码

        参数:
            mask1: 第一个掩码
            mask2: 第二个掩码
            operation: 操作类型 ('or', 'and', 'xor')

        返回:
            np.ndarray: 组合后的掩码
        """
        if operation == 'or':
            return cv2.bitwise_or(mask1, mask2)
        elif operation == 'and':
            return cv2.bitwise_and(mask1, mask2)
        elif operation == 'xor':
            return cv2.bitwise_xor(mask1, mask2)
        else:
            raise ValueError(f"Unsupported operation: {operation}")

    def get_mask_area(self, mask: np.ndarray) -> int:
        """
        获取掩码的面积（非零像素数量）

        参数:
            mask: 输入掩码

        返回:
            int: 掩码面积
        """
        return np.count_nonzero(mask)
